package com.youkang.youkangseleniumjava.utils;

import cn.hutool.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;

/**
 * @author LiXiang
 * @version V1.0.1
 * 注意 本内容仅限于长护宝科技有限公司，禁止外泄以及用于其他的商业
 * @projectName CloseableHttpClientUtil
 * @package com.changhubao.chb.utils
 * @description
 * @DATE: 2022/1/12
 * @TIME: 3:42 下午
 * @YEAR: 2022
 */
public class CloseableHttpClientUtil {
    private static CloseableHttpClient httpClient = null;

    public static final Logger logger = LoggerFactory.getLogger(CloseableHttpClientUtil.class);
    /**
     * post请求
     * @param json
     * @param url
     * @return
     */
    public static String post2(String json, String url,Map<String, String> heaMap){

        /**
         ** headerMap是添加的请求头，
         body是传入的参数，这里选择json，后端使用@RequestBody接收
         */

        cn.hutool.http.HttpResponse response = null;
        try {
            response = HttpRequest.post(url)
                    .headerMap(heaMap, false)
                    .body(json)
                    .timeout(20000)
                    .execute();
            //有个坑超过21秒会导致失效，注意
        } catch (Exception e) {
            System.out.println(e.getMessage());
            response = null;
        }
        String res = response.body();
        return res;
    }
    /**
     * get请求
     * @param url
     * @return
     */
    public static String get2(String url,Map<String, String> heaMap){
        cn.hutool.http.HttpResponse response = null;
        try {
            response = HttpRequest.get(url).timeout(20000)
                    .headerMap(heaMap, false).execute();
        }catch (Exception e) {
            response = null;
        }
        String res = response.body();
        return res;
    }

    /**
     * 以get方式调用第三方接口
     *
     * @param url
     * @param token
     * @return
     */
    public static String doGet(String url, String token, Map<String, String> header) {
        //创建HttpClient对象
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        HttpGet httpGet = new HttpGet(url);
        if (header.size() != 0) {
            for (String key : header.keySet()) {
                String value = header.get(key);
                httpGet.addHeader(key, value);
            }
        }
        try {
            HttpResponse response = httpClient.execute(httpGet);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                //返回json格式
                String res = EntityUtils.toString(response.getEntity());
                return res;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 以post方式调用第三方接口
     *
     * @param url
     * @param data
     * @return
     */
    public static String doPost(String url, Map<String, String> data, Map<String, String> header) {
        if (null == httpClient) {
            httpClient = HttpClientBuilder.create().build();
        }

        try {

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
            if (header.size() != 0) {
                for (String key : header.keySet()) {
                    String value = header.get(key);
                    headers.add(key, value);
                }
            }
            RestTemplate restTemplate = new RestTemplate();
            MultiValueMap<String, String> forms = new LinkedMultiValueMap<String, String>();
            if (data.size() != 0) {
                for (String key : data.keySet()) {
                    String value = data.get(key);
                    forms.put(key, Collections.singletonList(value));
                }
            }
            HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<MultiValueMap<String, String>>(forms, headers);

            //获取返回数据
            String body = restTemplate.postForObject(url, httpEntity, String.class);
            return body;

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (httpClient != null) {
                try {
                    httpClient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }
    /**
     * @param url 访问地址
     *  @param param 需要传输参数参数；对象可以通过json转换成String
     * @param header header 参数；可以通过下面工具类将string类型转换成map
     * @return 返回网页返回的数据
     */
    public static String doPostRaw(String url, String param, Map<String, String> header) throws UnsupportedEncodingException, IOException {
        OutputStreamWriter out;
        BufferedReader in = null;
        String result = "";
        URL realUrl = new URL(url);
        // 打开和URL之间的连接
        HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
        //设置超时时间
        conn.setConnectTimeout(5000000);
        conn.setReadTimeout(15000000);
        // 设置通用的请求属性
        if (header!=null) {
            for (Entry<String, String> entry : header.entrySet()) {
                conn.setRequestProperty(entry.getKey(), entry.getValue());
            }
        }
        conn.setRequestMethod("POST");
        conn.addRequestProperty("Content-Type", "application/json");
        conn.setRequestProperty("accept", "*/*");
        conn.setRequestProperty("connection", "Keep-Alive");
        conn.setRequestProperty("user-agent",
                "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
        // 发送POST请求必须设置如下两行
        conn.setDoOutput(true);
        conn.setDoInput(true);
        // 获取URLConnection对象对应的输出流
        out = new OutputStreamWriter( conn.getOutputStream(),"UTF-8");// utf-8编码
        // 发送请求参数
        out.write(param);

        // flush输出流的缓冲
        out.flush();
        // 定义BufferedReader输入流来读取URL的响应
        in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf8"));
        String line;
        while ((line = in.readLine()) != null) {
            result += line;
        }
        if(out!=null){
            out.close();
        }
        if(in!=null){
            in.close();
        }
        return result;
    }
    /**
     * post请求提交form-data上传文件
     *
     * @param url 上传地址
     * @param headers 请求头
     * @param file 上传文件
     * @return
     */
    public static String doPostUploadFile(String url, Map<String, String> headers, File file,Map<String, String> data) {
        HttpPost httpPost = new HttpPost(url);
        packageHeader(headers, httpPost);
        String fileName = file.getName();

        CloseableHttpResponse response = null;

        String respContent = null;

        long startTime = System.currentTimeMillis();

        // 设置请求头 boundary边界不可重复，重复会导致提交失败
        String boundary = "-------------------------" + UUID.randomUUID().toString();
        httpPost.setHeader("Content-Type", "multipart/form-data; boundary=" + boundary);

        // 创建MultipartEntityBuilder
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        // 设置字符编码
        builder.setCharset(StandardCharsets.UTF_8);
        // 模拟浏览器
        builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
        // 设置边界
        builder.setBoundary(boundary);
        // 设置multipart/form-data流文件
        builder.addPart("file", new FileBody(file));
        if (data.size() != 0) {
            for (String key : data.keySet()) {
                String value = data.get(key);
                builder.addTextBody(key, value);
            }
        }

        builder.addTextBody("fileType", "1");
        // application/octet-stream代表不知道是什么格式的文件
        builder.addBinaryBody("media", file, ContentType.create("application/octet-stream"), fileName);

        org.apache.http.HttpEntity entity = builder.build();
        httpPost.setEntity(entity);
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            response = httpClient.execute(httpPost);
            if (response != null && response.getStatusLine() != null && response.getStatusLine().getStatusCode() < 400) {

                org.apache.http.HttpEntity he = response.getEntity();
                if (he != null) {
                    respContent = EntityUtils.toString(he, "UTF-8");
                }
            } else {
                logger.error("对方响应的状态码不在符合的范围内!");
                throw new RuntimeException();
            }
            return respContent;
        } catch (Exception e) {
            logger.error("网络访问异常,请求url地址={},响应体={},error={}", url, response, e);
            throw new RuntimeException();
        } finally {
            logger.info("统一外网请求参数打印,post请求url地址={},响应={},耗时={}毫秒", url, respContent, (System.currentTimeMillis() - startTime));
            try {
                if (response != null) {
                    response.close();
                }
                if(null != httpClient){
                    httpClient.close();
                }
            } catch (IOException e) {
                logger.error("请求链接释放异常", e);
            }
        }
    }



    /**
     * 封装请求头
     *
     * @param paramsHeads
     * @param httpMethod
     */
    private static void packageHeader(Map<String, String> paramsHeads, HttpRequestBase httpMethod) {
        if (null!= paramsHeads && paramsHeads.size()>0) {
            Set<Entry<String, String>> entrySet = paramsHeads.entrySet();
            for (Entry<String, String> entry : entrySet) {
                httpMethod.setHeader(entry.getKey(), entry.getValue());
            }
        }
    }

    /**
     * 测试
     */
    public static void main(String[] args) throws IOException {

    }

}
